#pragma once
#include "binaryds.h"
#include "StackDS.h"

//#ifdef _UNICODE
#define MLSCHAR WCHAR
//#else
//#define MLSCHAR BYTE
//#endif

#define	mlsch_NewLine 0x80
#define	mlsch_ReverseIndent 0xF5
#define	mlsch_HardSpace 0xFC
#define	mlsch_ZeroSpace 0xFD
#define	mlsch_Embed 0xFA
#define	mlsch_Delimiter 0xFB
#define	mlsch_Semicolon 0x3B

#define	mlsfl_UnderLine 0x01
#define	mlsfl_Strike 0x02
#define	mlsfl_Accented 0x08

class CMLSScanner :
	protected  CBinaryDS
{
public:
	enum MLSToken {
		mlstk_EndOfFile
		,mlstk_Character
		,mlstk_Semicolon
		,mlstk_NewLine
		,mlstk_Delimiter
		,mlstk_Embed
		,mlstk_HardSpace
		,mlstk_ReverseIndent
		,mlstk_ZeroSpace
		,mlstk_NoToken
	};

public:
// Document -------------------------------------------------------------------------
	// Class
	CMLSScanner(void);
	~CMLSScanner(void);
	// File Management
	BOOL Open(CString FileName);
	void Close(void);
	// Reading Header Data
	CString GetVersion(void) {return Version;}
	CString GetPrevDoc(void) {return PrevDoc;}
	CString GetNextDoc(void) {return NextDoc;}
	BOOL GetIsLangSupported(int n) {return bIsLangSupported[n];}

// Streaming and Current Character Retrival------------------------------------------
	// Stream Read Token
	MLSToken GetToken(void);

	// Ahead Reading Token
	MLSToken GetTokenAhead(void);
	MLSToken GetSecToken(void);

	// Reading Current Token Data
	MLSCHAR GetTarget() {return TargetCharacter;}
	BYTE GetRaw() {return RawCharacter;}
	int GetLanguage() {return Language;}
	BYTE GetRawAhead();
	int GetLangAhead();

// Current Character Case Retrival --------------------------------------------------
	BOOL IsUnderLined() {return Flags & mlsfl_UnderLine;}
	BOOL IsStriked() {return Flags & mlsfl_Strike;}
	BOOL IsAccented() {return Flags & mlsfl_Accented;}
// Error Support --------------------------------------------------------------------
	int GetParaNo(){return CurrentParagraph;}
	int GetCharNo(){return CurrentCharacter;}
	int GetGlobalChar(){return CurrentGlobalCharacter;}

// Conversion Settings --------------------------------------------------------------
	// Modify Setings
	void SetLanguages(int Rmn, int Arab, int Copt)
	{Roman = Rmn; Arabic = Arab; Coptic = Copt;}

// Protected Procedures -------------------------------------------------------------
protected:
	MLSToken FillStack();
	MLSToken ResolveToken(BYTE Raw, int Lang);
	CMLSScanner::MLSToken PopTarget();
	void PushChar(BYTE Raw, int Lang);
	void PushPreAccent(WORD AccentsPattern, int Lang);
	void PushPostAccent(WORD AccentsPattern, int Lang);

// Data Members ---------------------------------------------------------------------
protected:
	// Output Data
	MLSCHAR TargetCharacter;
	BYTE RawCharacter;
	WORD Accents;
	int Language;
	int StackLang;
	int Flags;
	int CurrentParagraph;
	int CurrentCharacter;
	int CurrentGlobalCharacter;
	//Status
	CStackDS Stack;
	// File Header Data
	BOOL bIsLangSupported[5];
	CString Version;
	CString PrevDoc;
	CString NextDoc;
	// File Conversion Setup
	int Roman;
	int Arabic;
	int Coptic;
	int Greek;
	// Conversion Tables
	static MLSCHAR RomanChar[256];
	static MLSCHAR ArabicChar[256];
	static MLSCHAR CopticChar[256];
	static MLSCHAR GreekChar[256];
	static BYTE RomanAccent[20];
	static BYTE ArabicAccent[20];
	static BYTE CopticAccent[20];
	static BYTE GreekAccent[20];
};
